package cn.bass.marketing.common.utils.date;

import cn.bass.marketing.common.enums.ErrorEnums;
import cn.bass.marketing.common.exception.AppException;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

@Slf4j
public class DateUtils {

    public final static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public final static String DATE_FORMAT_YYYYMMDD = "yyyy-MM-dd";

    public final static String DATE_FORMAT_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public final static String DATE_FORMAT_YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";

    public final static String DATE_FORMAT_HHMMSS = "HH:mm:ss";

    /**
     * 字符串格式化时间
     *
     * @param format 格式
     * @param time   时间字符串
     * @return Date
     */
    public static Date formatTime(String format, String time) {

        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(time);
        } catch (ParseException e) {
            return null;
        }
    }

    public static String formatTime(String format, Date time) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(time);
    }

    public static Date parseDateTime(String date) {
        return formatTime(DATE_FORMAT, date);
    }

    public static String formatDate(Date date) {
        return formatTime(DATE_FORMAT_YYYYMMDD, date);
    }

    public static boolean isTimeWithinRange(Date currentTime, Date startTime, Date endTime) {
        return !currentTime.before(startTime) && !currentTime.after(endTime);
    }

    /**
     * 获取本月剩余天数
     * @return 剩余天数
     */
    public static int getMonthDayNumber(){
        LocalDate currentDate = LocalDate.now();
        int monthDays = YearMonth.now().lengthOfMonth();
        int passedDays = currentDate.getDayOfMonth() - 1;
        return monthDays - passedDays;
    }

    /**
     * {@code @title} 计算本天的开始时间
     * @return Date xxxx年xx月xx日  00:00:00
     */
    public static Date getTodayStart(Date startDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static LocalTime setLocalTime(Integer hour, Integer minute, Integer second){
        return LocalTime.of(hour, minute, second);
    }


    /**
     * {@code @title} 计算当天的结束时间
     * @return Date xxxx年xx月xx日 23:59:59
     */
    public static Date getTodayEnd(Date endDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(endDate);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * {@code @title} 计算本周的开始时间
     * @return Date xxxx年xx月xx日  00:00:00
     */
    public static Date getWeekStart() {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算本周的开始时间
        LocalDate startOfWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        return Date.from(startOfWeek.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * {@code @title} 计算本周的结束时间
     * @return Date xxxx年xx月xx日 23:59:59
     */
    public static Date getWeekEnd() {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算本周的开始时间和结束时间
        LocalDate endOfWeek = currentDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        return getTodayEnd(Date.from(endOfWeek.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    }

    /**
     * {@code @title} 计算本月的开始时间
     * @return Date xxxx年xx月xx日  00:00:00
     */
    public static Date getMonthStart(){
        // 获取当前日期和时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        // 计算本月的开始时间和结束时间
        LocalDate startOfMonth = currentDateTime.toLocalDate().with(TemporalAdjusters.firstDayOfMonth());
        return Date.from(startOfMonth.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * {@code @title} 计算本月的结束时间
     * @return Date xxxx年xx月xx日  23:59:59
     */
    public static Date getMonthEnd(){
        // 获取当前日期和时间
        LocalDate currentDate = LocalDate.now();
        // 计算本月的结束时间
        LocalDate endOfMonth = currentDate.with(TemporalAdjusters.lastDayOfMonth());
        return getTodayEnd(Date.from(endOfMonth.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    }


    /**
     * 获取当天的结束分钟数
     * @return 分钟数
     */
    public static long getDayUntil() {
        LocalTime currentTime = LocalTime.now();
        LocalTime endOfDay = LocalTime.of(23, 59, 59);
        return currentTime.until(endOfDay, ChronoUnit.MINUTES);
    }

    public static boolean isBeforeDateRange(Date newDate, Date startDate) {
        return newDate.before(startDate);
    }

    public static boolean isAfterDateRange(Date newDate, Date endDate) {
        return newDate.after(endDate);
    }


    public static boolean rangeDate(Date startDate, Date endDate) {
        Date checkDate = new Date();
        return checkDate.after(startDate) && checkDate.before(endDate);
    }

    public static String getCurrentWeekDayNumber() {
        LocalDate today = LocalDate.now();
        // 获取星期几的数字表示
        return String.valueOf(today.getDayOfWeek().getValue());
    }

    public static String getCurrentWeekDayNumberStr() {
        LocalDate today = LocalDate.now();
        // 获取星期几的数字表示
        int value = today.getDayOfWeek().getValue();
        switch (value) {
            case 1 :
                return "星期一";
            case 2 :
                return "星期二";
            case 3 :
                return "星期三";
            case 4 :
                return "星期四";
            case 5 :
                return "星期五";
            case 6 :
                return "星期六";
            case 7 :
                return "星期日";
            default:
                throw new AppException(ErrorEnums.FORMAT_WEEK_ERROR.getCode(), ErrorEnums.FORMAT_WEEK_ERROR.getMsg());
        }
    }


    public static void main(String[] args) throws ParseException {
//        ActivityTimesDto activityTimesDto = new ActivityTimesDto();
//        List<Map<String, String>> listMap = new ArrayList<>();
//        listMap.add(new HashMap<String, String>() {{
//            put("startTime", "11:28:00");
//            put("endTime", "14:28:00");
//        }});
//        listMap.add(new HashMap<String, String>() {{
//            put("startTime", "14:30:00");
//            put("endTime", "14:50:00");
//        }});
//        LocalTime currentTime = LocalTime.parse("16:29:00");
//        listMap.sort(Comparator.comparing(map -> LocalTime.parse(map.get("endTime"))));
//        LocalTime activityStartTime = null;
//        LocalTime activityEndTime = null;
//        LocalDate currentDate = LocalDate.now();
//        for (Map<String, String> timeMap : listMap) {
//            LocalTime startTime = LocalTime.parse(timeMap.get("startTime"));
//            LocalTime endTime = LocalTime.parse(timeMap.get("endTime"));
//            if (currentTime.isAfter(startTime) && currentTime.isBefore(endTime)) {
//                activityStartTime = startTime;
//                activityEndTime = endTime;
//                activityTimesDto.setStartLocalTime(currentDate.atTime(startTime));
//                activityTimesDto.setEndLocalTime(currentDate.atTime(endTime));
//                break;
//            }
//            // 如果当前时间在某个时间段的结束时间之前，则取下一个时间段的开始时间和结束时间
//            if (currentTime.isBefore(endTime)) {
//                activityStartTime = startTime;
//                activityEndTime = endTime;
//                activityTimesDto.setStartLocalTime(currentDate.atTime(startTime));
//                activityTimesDto.setEndLocalTime(currentDate.atTime(endTime));
//                break;
//            }
//        }
//
//        // 不在任何场次或者没有场次，则取当前时间最近的开始时间和结束时间场次
//        if (Objects.isNull(activityStartTime) || Objects.isNull(activityEndTime)) {
//            long nearestTimeDifference = Long.MAX_VALUE;
//            for (Map<String, String> timeMap : listMap) {
//                LocalTime startTime = LocalTime.parse(timeMap.get("startTime"));
//                LocalTime endTime = LocalTime.parse(timeMap.get("endTime"));
//                long startTimeDifference = Math.abs(currentTime.toNanoOfDay() - startTime.toNanoOfDay());
//                long endTimeDifference = Math.abs(currentTime.toNanoOfDay() - endTime.toNanoOfDay());
//                long minDifference = Math.min(startTimeDifference, endTimeDifference);
//                if (minDifference < nearestTimeDifference) {
//                    activityStartTime = startTime;
//                    activityEndTime = endTime;
//                    nearestTimeDifference = minDifference;
//                }
//            }
//            if (activityStartTime != null) {
//                activityTimesDto.setStartLocalTime(currentDate.atTime(activityStartTime));
//            }
//            if (activityEndTime != null) {
//                activityTimesDto.setEndLocalTime(currentDate.atTime(activityEndTime));
//            }
//        }
//        System.out.println("Next Start Time: " + activityTimesDto.getStartLocalTime());
//        System.out.println("Next End Time: " + activityTimesDto.getEndLocalTime());
    }

    public static String getDateFormatYyyymmddhhmmss(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YYYYMMDDHHMMSSSSS);
        return sdf.format(date);
    }
}
